/* -+- file  ./kf2/GUI/ItemMenu.cs -+- */
/*
 * kf2 jabber client
 * ~~~~~~~~~~~~~~~~~
 *
 * Copyright (C) 2006-2007 Przemysław Sitek
 * 				<przemyslaw.sitek at wp.pl> 
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

using System;
using System.Collections.Generic;
using Mono.Unix;
using Habazie.kf2.Core;
using Habazie.kf2.Exposition;
using Habazie.kf2.Net;
using Habazie.kf2.Roster;

namespace Habazie.kf2.GUI
{
	public delegate void ActionEventHandler (object o, ActionEventArgs args);
	public enum ActionType { Remove, GroupAdd, GroupEdit, GroupSet, GroupClear, Rename };
	public class ActionEventArgs : EventArgs
	{
		private ActionType m_Action;
		private Item m_Item;
		private string m_text = null;

		public ActionEventArgs (Item item, ActionType a)
		{
			m_Item = item;
			m_Action = a;

		}
		public ActionEventArgs (Item item, ActionType a, string opt) : this (item, a)
		{
			m_text = opt;
		}
		public Habazie.kf2.Roster.Item Item {
			get { return m_Item; }
			set { m_Item = value; }
		}
		public ActionType Action {
			get { return m_Action; }
			set { m_Action = value; }
		}
		public string Text {
			get { return m_text; }
			set { m_text = value; }
		}
	}
	
	public class ItemMenu : Gtk.Menu
	{
		private Account m_Account;
		private Item m_Item;
		
		public event ActionEventHandler ActionPerformed = null;
		
		public ItemMenu(Item item) : base ()
		{
			m_Account = item.Account;
			m_Item = item;
			
			Gtk.ImageMenuItem ii;
			Gtk.MenuItem i;
			
			ii = new Gtk.ImageMenuItem (Catalog.GetString ("Chat"));
			ii.Image = new Gtk.Image (Pixbufs.Image (Pixbuf.Chat));
			ii.Image.Show ();
			ii.Activated += OnChat;
			Append (ii);
			ii.Show ();
			
			ii = new Gtk.ImageMenuItem (Catalog.GetString ("Message"));
			ii.Image = new Gtk.Image (Pixbufs.Image (Pixbuf.Message));
			ii.Image.Show ();
			ii.Activated += OnMessage;
			Append (ii);
			ii.Show ();
			
			i = new Gtk.MenuItem (Catalog.GetString ("Resources"));
			Gtk.Menu resources = ResourcesSubmenu ();
			if (resources != null)
				i.Submenu = resources;
			else
				i.Sensitive = false;
			Append (i);
			i.Show ();
			
			i = new Gtk.MenuItem (Catalog.GetString ("Active Chats"));
			Gtk.Menu active = ActiveSubmenu ();
			if (active != null)
				i.Submenu = active;
			else
				i.Sensitive = false;
			Append (i);
			i.Show ();
			
			i = new Gtk.SeparatorMenuItem ();
			Append (i);
			i.Show ();
			
			i = new Gtk.MenuItem (Catalog.GetString ("History"));
//			i.Activated += OnChat;
			Append (i);
			i.Sensitive = false;
			i.Show ();
			
			i = new Gtk.MenuItem (Catalog.GetString ("Information"));
			i.Activated += OnInfo;
			Append (i);
			i.Show ();
			
			i = new Gtk.SeparatorMenuItem ();
			Append (i);
			i.Show ();
			
			i = new Gtk.MenuItem (Catalog.GetString ("Presence"));
			i.Submenu = PresenceSubmenu ();
			Append (i);
			i.Show ();
			
			i = new Gtk.MenuItem (Catalog.GetString ("Rename"));
			Append (i);
			i.Activated += delegate (object o, EventArgs args) {
				if (ActionPerformed != null)
					ActionPerformed (this, new ActionEventArgs (m_Item,
							       ActionType.Rename));
			};
		//	i.Sensitive = false;
			i.Show ();
			
			i = new Gtk.MenuItem (Catalog.GetString ("Group"));
			Gtk.Menu group = GroupSubmenu ();
			i.Submenu = group;
			Append (i);
		//	i.Sensitive = false;
			i.Show ();
			
			i = new Gtk.SeparatorMenuItem ();
			Append (i);
			i.Show ();
			
			ii = new Gtk.ImageMenuItem (Catalog.GetString ("Remove"));
			ii.Image = new Gtk.Image (Gtk.Stock.Remove, Gtk.IconSize.Menu);
			ii.Image.Show ();
			ii.Activated += OnRemove;
//			ii.Sensitive = false;
			Append (ii);
			ii.Show ();
		}
		
		private Gtk.Menu ResourcesSubmenu ()
		{
			if (m_Item.Resources.Count == 0)
				return null;
				
			Gtk.Menu menu = new Gtk.Menu ();
			
			foreach (Resource r in m_Item.Resources) {
				
				Gtk.ImageMenuItem i;
				
				Gtk.Image img = new Gtk.Image (Pixbufs.Get (r.Presence, r.Show));
				img.Show ();
				
				string title = (r.Name != null)
							?String.Format ("{0} ({1})",r.Name, r.Priority)
							:"default";
				
				i = new LabelMenuItem (title);
				i.Image = img;
				menu.Append (i);
				i.Show ();
				
				i = new Gtk.ImageMenuItem (Catalog.GetString ("Chat"));
				i.Name = r.Name;
				i.Activated += delegate {
					jabber.JID jid = new jabber.JID (m_Item.JabberID.User, m_Item.JabberID.Server, i.Name);
					Chat win = Chat.Get (m_Account, jid);
					win.Show ();
				};
				menu.Append (i);
				i.Show ();
				
				i = new Gtk.ImageMenuItem (Catalog.GetString ("Message"));
				i.Name = r.Name;
				i.Activated += delegate {
					jabber.JID jid = new jabber.JID (m_Item.JabberID.User, m_Item.JabberID.Server, i.Name);
					NewMessage win = new NewMessage (m_Account);
					win.To = jid;
					win.Show ();
				};
				menu.Append (i);
				i.Show ();
			}
			menu.ShowAll ();
			return menu;
		}
			
		private Gtk.Menu ActiveSubmenu ()
		{
			Gtk.Menu menu = new Gtk.Menu ();
			int n_items = 0;
			
			foreach (Chat c in Chat.All) {
				if (c.GetJID().Bare == m_Item.JabberID.Bare) {
					ChatMenuItem i;
				
					Resource r = m_Item.GetResource (c.GetJID ().Resource);
					i = new ChatMenuItem (c.GetJID ().Resource);
					i.Chat = c;
					i.Activated += OnActiveChatActivated;
					if (r != null) {
						Gtk.Image img = new Gtk.Image (Pixbufs.Get (r.Presence, r.Show));
						img.Show ();
						i.Image = img;
					}
					menu.Append (i);
					n_items++;
					
					i.Show ();
				}
			}
			if (n_items == 0)
				return null;
			menu.Show ();
			return menu;
		}

		private Gtk.Menu GroupSubmenu ()
		{
			List<string> groups = new List<string>  ();
			foreach (Item item in m_Account.GetRosterRef ())
				foreach (string g in item.Groups)
					if (! groups.Contains (g))
						groups.Add (g);
			groups.Sort ();

			Gtk.Menu m = new Gtk.Menu ();
			TextMenuItem i;

			i = new TextMenuItem (Catalog.GetString ("New group..."));
			i.Image = new Gtk.Image (Gtk.Stock.Add, Gtk.IconSize.Menu);
			i.Image.Show ();
			i.Activated += delegate (object o, EventArgs args) {
				if (ActionPerformed != null)
					ActionPerformed (this, new ActionEventArgs (m_Item,
							       ActionType.GroupAdd));
			};
			m.Append (i);
			i.Show ();

			i = new TextMenuItem (Catalog.GetString ("Edit groups"));
			i.Image = new Gtk.Image (Gtk.Stock.Properties, Gtk.IconSize.Menu);
		//	i.Image.Show ();
			i.Activated += delegate (object o, EventArgs args) {
				if (ActionPerformed != null)
					ActionPerformed (this, new ActionEventArgs (m_Item,
							       ActionType.GroupEdit));
			};
			i.Sensitive = false;
			m.Append (i);
			i.Show ();

			i = new TextMenuItem (Catalog.GetString ("Clear groups"));
			i.Image = new Gtk.Image (Gtk.Stock.Clear, Gtk.IconSize.Menu);
			i.Image.Show ();
			i.Activated += delegate (object o, EventArgs args) {
				if (ActionPerformed != null)
					ActionPerformed (this, new ActionEventArgs (m_Item,
							       ActionType.GroupClear));
			};
			m.Append (i);
			i.Show ();


			Gtk.SeparatorMenuItem sep = new Gtk.SeparatorMenuItem ();
			m.Append (sep);
			sep.Show ();

			foreach (string g in groups) {
				i = new TextMenuItem (g);
				i.XText = g;
				i.Activated += delegate (object o, EventArgs args) {
					TextMenuItem mi = o as TextMenuItem;
					if (ActionPerformed != null)
						ActionPerformed (this, new ActionEventArgs (m_Item,
								       ActionType.GroupSet, mi.XText));
				};
				m.Append (i);
				i.Show ();
			}

			m.ShowAll (); // why? dunno...
			return m;
		}
		
		
		private Gtk.Menu PresenceSubmenu ()
		{
			Gtk.Menu m = new Gtk.Menu ();
			Gtk.ImageMenuItem item;

			item = new Gtk.ImageMenuItem (Catalog.GetString ("Send Online"));
			m.Append (item);
			                     
			item = new Gtk.ImageMenuItem (Catalog.GetString ("Send Unavailable"));
			m.Append (item);
			
			Gtk.SeparatorMenuItem separator = new Gtk.SeparatorMenuItem ();
			m.Append (separator);

			item = new Gtk.ImageMenuItem (Catalog.GetString ("Ask"));
			m.Append (item);
			
			item = new Gtk.ImageMenuItem (Catalog.GetString ("Give"));
			m.Append (item);
			
			item = new Gtk.ImageMenuItem (Catalog.GetString ("Deny"));
			m.Append (item);
			
			
			m.ShowAll ();
			return m;
		}
		
		
		protected virtual void OnActiveChatActivated (object o, EventArgs args)
		{
			ChatMenuItem item = (ChatMenuItem) o;
			Chat chat = item.Chat;
			
			chat.Show ();
			chat.Raise ();
		}
		
		
		protected virtual void OnChat (object o, EventArgs args)
		{
//			Chat win = Chat.Get (m_Account, m_Item.JabberID);
			Chat win = Chat.Get (m_Item);
			win.Show ();
		}
		
		protected virtual void OnMessage (object o, EventArgs args)
		{
			NewMessage win = new NewMessage (m_Account);
			win.To = m_Item.JabberID;
			win.Show ();
		}
		
		protected virtual void OnInfo (object o, EventArgs args)
		{
			m_Item.UpdateVCard ();
			
			VCard v = new VCard (m_Account);
			v.Item = m_Item;
			v.Retrieve ();
		}
		
		
		protected virtual void OnRemove (object o, EventArgs args)
		{
			if (ActionPerformed != null)
				ActionPerformed (this, new ActionEventArgs (m_Item, ActionType.Remove));
		}
	}


	public class TextMenuItem : Gtk.ImageMenuItem
	{
		private string m_str = null;

		public TextMenuItem (string s) : base (s)
		{
		}

		public string XText {
			get { return m_str; }
			set { m_str = value; }
		}
	}
	
	public class ChatMenuItem : Gtk.ImageMenuItem
	{
		private Chat m_chat;
		
		public ChatMenuItem (string text) : base ()
		{
			Gtk.Label label = new Gtk.Label (text);
			label.Show ();
			Add (label);
		}
		
		
		public Habazie.kf2.GUI.Chat Chat {
			get { return m_chat; }
			set { m_chat = value; }
		}
	}
}
